/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package PhysicCollection;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;

/**
 *
 * @author danh.ngothanh
 */
public class ReflectExample extends JPanel implements MouseListener, Runnable{
    double baseX1, baseY1, baseX2, baseY2;
    double baseLength;
    double[] xCoords, yCoords;
    double ellipseX, ellipseY, ellipseRadius = 6;
    double directionX, directionY;
    double ellipseSpeed = 3.5;
    double velocityX, velocityY;


    void setup(){
      baseX1 = 0;
      baseY1 = getHeight()-150;
      baseX2 = getWidth();
      baseY2 = getHeight();

      // start ellipse at middle top of screen
      ellipseX = getWidth()/2;

      // calculate initial random direction
      directionX = Math.max(0.1, 0.99);
      directionY = Math.max(0.1, 0.99);

      // normalize direction vector
      double directionVectLength = Math.sqrt(directionX*directionX +directionY*directionY);
      directionX /= directionVectLength;
      directionY /= directionVectLength;
    }
    @Override
    public void paint(Graphics g){
         // draw background
      g.setColor(Color.WHITE);
      g.fillRect(0, 0, getWidth(), getHeight());
      // calculate length of base top
      baseLength = Math.sqrt(Math.pow(baseX1 - baseX2,2) + Math.pow(baseY2 - baseY1,2));
      xCoords = new double[(int)(baseLength)];
      yCoords = new double[(int)(baseLength)];

      // fill base top coordinate array
      for (int i=0; i<xCoords.length; i++){
        xCoords[i] = baseX1 + ((baseX2-baseX1)/baseLength)*i;
        yCoords[i] = baseY1 + ((baseY2-baseY1)/baseLength)*i;
      }

//      // draw base
//      fill(200);
//      quad(baseX1, baseY1, baseX2, baseY2, baseX2, height, 0, height);

      // calculate base top normal
      double baseDeltaX = (baseX2-baseX1)/baseLength;
      double baseDeltaY = (baseY2-baseY1)/baseLength;
      double normalX = -baseDeltaY;
      double normalY = baseDeltaX;

      // draw ellipse
      g.setColor(Color.red);
      g.fillOval((int)ellipseX, (int)ellipseY, (int)ellipseRadius*2, (int)ellipseRadius*2);

      // calculate ellipse velocity
      velocityX = directionX * ellipseSpeed;
      velocityY = directionY * ellipseSpeed;

      // move elipse
      ellipseX += velocityX;
      ellipseY += velocityY;

      // normalized incidence vector
      double incidenceVectorX = -directionX;
      double incidenceVectorY = -directionY;

      // detect and handle collision
      for (int i=0; i<xCoords.length; i++){
        // check distance between ellipse and base top coordinates
//        if (dist(ellipseX, ellipseY, xCoords[i], yCoords[i]) < ellipseRadius){
          if ((Math.sqrt(Math.pow( xCoords[i] - ellipseX ,2) + Math.pow(yCoords[i] - ellipseY, 2))) < ellipseRadius){

          // calculate dot product of incident vector and base top normal
          double dot = incidenceVectorX*normalX + incidenceVectorY*normalY;

          // calculate reflection vector
          double reflectionVectorX = 2*normalX*dot - incidenceVectorX;
          double reflectionVectorY = 2*normalY*dot - incidenceVectorY;

          // assign reflection vector to direction vector
          directionX = reflectionVectorX;
          directionY = reflectionVectorY;

          // draw base top normal at collision point
          g.setColor(Color.BLUE);
          g.drawLine((int)ellipseX, (int)ellipseY, (int)(ellipseX-normalX*100),(int)(ellipseY-normalY*100));
        }
      }

      // detect boundary collision
      // right
      if (ellipseX > getWidth()-ellipseRadius){
        ellipseX = getWidth()-ellipseRadius;
        directionX *= -1;
      }
      // left
      if (ellipseX < ellipseRadius){
        ellipseX = ellipseRadius;
        directionX *= -1;
      }
      // top
      if (ellipseY < ellipseRadius){
        ellipseY = ellipseRadius;
        directionY *= -1;
        // randomize base top
        baseY1 = Math.max(getHeight()-100, getHeight());
        baseY2 = Math.max(getHeight()-100, getHeight());
      }
    }

    public void mouseClicked(MouseEvent e) {
        repaint();
    }

    public void mousePressed(MouseEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseReleased(MouseEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseEntered(MouseEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseExited(MouseEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public void run(){
        repaint();
    }


}
